Option Strict Off
Imports CommonNamespace
Imports MetaView.AnnotatedImage
Imports ROIImageProcessingNamespace
Imports MetaView


Public Class AnnotatedsRGBImage
    'Class that contains an annotated image control and a status bar,
    'and adds color space knowledge to it. It also includes open and save dialog boxes
    Inherits System.Windows.Forms.UserControl
    'Inherits AnnotatedImage

    Public PassKey As String = ""
#Region " Windows Form Designer generated code "

    Public Sub New(Optional ByVal PassKeyWord As String = "notspecified")
        MyBase.New()
        Me.PassKey = PassKeyWord
        Debug.WriteLine("Initializing ...", "AnnotatedsRGBImage.New")
        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call
        'AddMenus()
        AddMenuswithBitmapLoad()
        Me.bModifiedImage = False
        Me.bModifiedImage = False

        Debug.WriteLine("Done", "AnnotatedsRGBImage.New")
    End Sub
    'Public Sub New()
    '    MyBase.New()
    '    Me.PassKey = ""
    '    Debug.WriteLine("Initializing ...", "AnnotatedsRGBImage.New")
    '    'This call is required by the Windows Form Designer.
    '    InitializeComponent()

    '    '    'Add any initialization after the InitializeComponent() call
    '    'AddMenus()
    '    AddMenuswithBitmapLoad()
    '    Me.bModifiedImage = False
    '    Me.bModifiedImage = False

    '    Debug.WriteLine("Done", "AnnotatedsRGBImage.New")
    'End Sub
    Public Sub New(ByVal ouri As Uri)
        MyBase.New()

        Debug.WriteLine("Initializing ...", "AnnotatedsRGBImage.New")
        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call
        Me.AddMenuswithBitmapLoad()
        Me.bModifiedImage = False
        Me.bModifiedImage = False

        Debug.WriteLine("Done", "AnnotatedsRGBImage.New")
    End Sub

    'UserControl1 overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents stbImage As System.Windows.Forms.StatusBar
    Friend WithEvents stpImageInfo As System.Windows.Forms.StatusBarPanel
    Friend WithEvents stpZoom As System.Windows.Forms.StatusBarPanel
    Friend WithEvents stpWindow As System.Windows.Forms.StatusBarPanel
    Friend WithEvents stpPos As System.Windows.Forms.StatusBarPanel
    Public WithEvents dlgSaveFile As System.Windows.Forms.SaveFileDialog
    Public WithEvents dlgOpenFile As System.Windows.Forms.OpenFileDialog
    Public WithEvents oAnnotatedImage As AnnotatedImage
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.stbImage = New System.Windows.Forms.StatusBar
        Me.stpImageInfo = New System.Windows.Forms.StatusBarPanel
        Me.stpZoom = New System.Windows.Forms.StatusBarPanel
        Me.stpWindow = New System.Windows.Forms.StatusBarPanel
        Me.stpPos = New System.Windows.Forms.StatusBarPanel
        Me.dlgSaveFile = New System.Windows.Forms.SaveFileDialog
        Me.dlgOpenFile = New System.Windows.Forms.OpenFileDialog
        Me.oAnnotatedImage = New AnnotatedImage
        Me.oAnnotatedImage.PassKey = Me.PassKey
        CType(Me.stpImageInfo, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.stpZoom, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.stpWindow, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.stpPos, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SuspendLayout()
        '
        'stbImage
        '
        Me.stbImage.Location = New System.Drawing.Point(0, 601)
        Me.stbImage.Name = "stbImage"
        Me.stbImage.Panels.AddRange(New System.Windows.Forms.StatusBarPanel() {Me.stpImageInfo, Me.stpZoom, Me.stpWindow, Me.stpPos})
        Me.stbImage.ShowPanels = True
        Me.stbImage.Size = New System.Drawing.Size(800, 24)
        Me.stbImage.SizingGrip = False
        Me.stbImage.TabIndex = 2
        Me.stbImage.Text = "StatusBar1"
        '
        'stpImageInfo
        '
        Me.stpImageInfo.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Contents
        Me.stpImageInfo.Text = "Image"
        Me.stpImageInfo.Width = 46
        '
        'stpZoom
        '
        Me.stpZoom.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Contents
        Me.stpZoom.MinWidth = 70
        Me.stpZoom.Text = "Zoom"
        Me.stpZoom.Width = 70
        '
        'stpWindow
        '
        Me.stpWindow.MinWidth = 75
        Me.stpWindow.Text = "Window"
        Me.stpWindow.Width = 75
        '
        'stpPos
        '
        Me.stpPos.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Spring
        Me.stpPos.Width = 609
        '
        'dlgSaveFile
        '
        Me.dlgSaveFile.FileName = "doc1"
        '
        'oAnnotatedImage
        '
        Me.oAnnotatedImage.AnnotationsManagerVisible = False
        Me.oAnnotatedImage.Bitmap = Nothing
        Me.oAnnotatedImage.Cursor = System.Windows.Forms.Cursors.Arrow
        Me.oAnnotatedImage.DisplayOffset = New System.Drawing.Point(0, 0)
        Me.oAnnotatedImage.DisplayZoom = 1.0!
        Me.oAnnotatedImage.Location = New System.Drawing.Point(0, 8)
        Me.oAnnotatedImage.MaximimumSize = New System.Drawing.Size(799, 599)
        Me.oAnnotatedImage.Name = "oAnnotatedImage"
        Me.oAnnotatedImage.PixelAveragingWindowSize = 0
        Me.oAnnotatedImage.Size = New System.Drawing.Size(799, 599)
        Me.oAnnotatedImage.TabIndex = 3
        Me.oAnnotatedImage.Text = "AnnotatedImage1"
        '
        'AnnotatedsRGBImage
        '
        Me.Controls.Add(Me.oAnnotatedImage)
        Me.Controls.Add(Me.stbImage)
        Me.Name = "AnnotatedsRGBImage"
        Me.Size = New System.Drawing.Size(800, 625)
        CType(Me.stpImageInfo, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.stpZoom, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.stpWindow, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.stpPos, System.ComponentModel.ISupportInitialize).EndInit()
        Me.ResumeLayout(False)

    End Sub

#End Region
    'Class variables
    Private objMaximimumSize As Size
    Private mniDisplayPixel As MenuItem, iWindowSize As Integer
    Private objColor As New ColorUtil

    'Keeping track of modifications to bitmap and annotations
    'It is impossible to now when the bitmap is modified, so it must be set manually!!!
    'This is not true for the annotations ...
    Dim bModifiedImage, bModifiedAnnotations As Boolean

    Public Enum PixelDisplayColorSpaceTypes
        None = 0
        sRGB
        GammasRGB
        CIEXYZ
        CIELab
    End Enum

    Private strPixelDisplayColorSpaceNames() As String = New String() {"None", "sRGB", "sR*G*B*", "CIE XYZ", "CIE L*a*b*"}
    Private iPixelDisplayColorSpace As PixelDisplayColorSpaceTypes = PixelDisplayColorSpaceTypes.GammasRGB

    'Public events from the custom annotated image control
    Public Event DisplayZoomChanged(ByVal sDisplayZoom As Single)
    Public Event PixelAveragingWindowSizeChanged(ByVal iWindowSize As Integer)
    Public Event BitmapChanged(ByVal objBitmap As Bitmap)
    Public Event BitmapDataChanged(ByVal objBitmap As Bitmap)
    Public Event AnnotationCreationDone(ByVal objAnnotation As AnnotatedImage.Annotation)
    Public Event AnnotationCreationCanceled(ByVal objAnnotation As AnnotatedImage.Annotation)
    Public Event AnnotationCreationPointAdded(ByVal objAnnotation As AnnotatedImage.Annotation)
    Public Event AnnotationCreationPointRemoved(ByVal objAnnotation As AnnotatedImage.Annotation)
    Public Event AnnotationItemSelected(ByVal obj As Object)
    Public Event AnnotationsUpdated()
    Public Event AnnotationCreationMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs, ByVal objAnnotation As AnnotatedImage.Annotation)
    Public Event AnnotationHover(ByVal e As System.Windows.Forms.MouseEventArgs, ByVal objAnnotation As AnnotatedImage.Annotation)
    Public Event AnnotationsChanged(ByVal sender As Object)
    Public Event AnnotationsManagerVisibleChanged(ByVal bTrue As Boolean)  'Visibility of annotation manager has changed

    '---------------------- Properties -----------------------

#Region "Properties"

    'Some of these properties are actually contained in the 
    'annotated image custom control.
    Public ReadOnly Property AnnotatedImage() As AnnotatedImage
        Get
            Return Me.oAnnotatedImage()
        End Get
    End Property

    Public ReadOnly Property AnnotatedArea() As Region()
        Get
            Return Me.oAnnotatedImage.GetRegion
        End Get
    End Property
    Public Property MaximimumSize() As Size
        Get
            Return Me.objMaximimumSize
        End Get
        Set(ByVal Value As Size)
            Me.objMaximimumSize = Value

            'Set property in image control too, adjusted for the extra controls
            Me.oAnnotatedImage.MaximimumSize = New Size(Value.Width, Value.Height - Me.stbImage.Height)
        End Set
    End Property

    Public Property PixelDisplayColorSpace() As PixelDisplayColorSpaceTypes
        Get
            Return Me.iPixelDisplayColorSpace
        End Get
        Set(ByVal Value As PixelDisplayColorSpaceTypes)
            If Not mniDisplayPixel Is Nothing Then
                With mniDisplayPixel
                    .MenuItems(iPixelDisplayColorSpace).Checked = False
                    .MenuItems(Value).Checked = True
                End With
                Me.iPixelDisplayColorSpace = Value
            End If

            If Value = PixelDisplayColorSpaceTypes.None Then
                Me.oAnnotatedImage.PixelAveragingWindowSize = 0
            End If
        End Set
    End Property

    Public ReadOnly Property OpenFileDialog() As OpenFileDialog
        Get
            Return Me.dlgOpenFile
        End Get
    End Property

    Public ReadOnly Property SaveFileDialog() As SaveFileDialog
        Get
            Return Me.dlgSaveFile
        End Get
    End Property

    Public Property ModifiedImage() As Boolean
        Get
            Return Me.bModifiedImage
        End Get
        Set(ByVal Value As Boolean)
            Me.bModifiedImage = Value
            SetFormTitle()
        End Set
    End Property

    Public Property ModifiedAnnotations() As Boolean
        Get
            Return Me.bModifiedAnnotations
        End Get
        Set(ByVal Value As Boolean)
            Me.bModifiedAnnotations = Value
            SetFormTitle()
        End Set
    End Property

    Private Sub SetFormTitle()
        Dim strMark As String = ""
        If Me.bModifiedAnnotations Then
            strMark = "+"
        End If
        If Me.bModifiedImage Then
            strMark = strMark & "*"
        End If

        If Not Me.ParentForm Is Nothing Then
            Me.ParentForm.Text = Application.ProductName & " ROI Viewer: " & strMark & " " + IIf(oAnnotatedImage.PassKey.ToLower.Contains("t"), "Transverse", IIf(oAnnotatedImage.PassKey.ToLower.Contains("c"), "Coronal", "Sagittal")) + " slice: " + oAnnotatedImage.PassKey.TrimStart(New Char() {"t", "s", "c"})

        End If
    End Sub
#End Region

#Region "Public methods"

#Region "IO"
    'For IO we shadow all functions of the AnnotatedImage control
    'If we want to use the 'modified' properties we need to use
    'these instead of the one of the AnnotatedImage control
    Public Overloads Sub LoadAnnotations()
        'Adds a dialog to deeper lying layers
        dlgOpenFile.Title = "Load an SVG annotations file"
        dlgOpenFile.Filter = "Scalable Vector graphics (*.svg)|*.svg|CSV Files (*.csv)|*.csv"
        dlgOpenFile.Multiselect = False
        dlgOpenFile.ShowDialog()

        If dlgOpenFile.FileName.Length > 0 Then
            Me.LoadAnnotations(New Uri(dlgOpenFile.FileName))
        End If
    End Sub

    Public Overloads Sub LoadAnnotations(ByVal oURI As Uri)
        Me.oAnnotatedImage.PassKey = Me.PassKey
        Me.oAnnotatedImage.LoadAnnotations(oURI)
        Me.ModifiedAnnotations = False
        Me.PassKey = Me.oAnnotatedImage.PassKey 'incase passkey is read from the file
    End Sub

    Public Function SaveAnnotationsAs() As Boolean
        'Adds a dialog to deeper lying layers
        dlgSaveFile.Title = "Save a SVG file"
        dlgSaveFile.Filter = "Scalable Vector graphics (*.svg)|*.svg"
        dlgSaveFile.AddExtension = True
        If dlgSaveFile.ShowDialog() = DialogResult.OK Then
            If dlgSaveFile.FileName.Length > 0 Then
                Return Me.SaveAnnotations(New Uri(dlgSaveFile.FileName))
            End If
        End If
        Return False
    End Function

    Public Overloads Function SaveAnnotations() As Boolean
        If Me.oAnnotatedImage.AnnotationsURI Is Nothing Then
            Debug.WriteLine("No URI present, showing filedialog ...", "AnnotatedsRGBImage.SaveAnnotations")
            Return Me.SaveAnnotationsAs
        Else
            Return Me.SaveAnnotationsAs
        End If
    End Function
    Public Overloads Function SaveAnnotations(ByVal oURI As Uri) As Boolean
        Dim bResult As Boolean = Me.oAnnotatedImage.SaveAnnotations(oURI)
        If bResult Then Me.ModifiedAnnotations = False
        Return bResult
    End Function
    Public Function SaveImageAs() As Boolean
        'Adds a dialog to deeper lying layers
        dlgSaveFile.Title = "Save an image"
        'dlgSaveFile.Filter = "Image files (*.jpg, *.png, *.bmp)|*.jpg;*.png;*.bmp|jpeg (*.jpg)|*.jpg|portable network graphic (*.png)|*.png|Windows bitmap (*.bmp)|*.bmp"
        dlgSaveFile.Filter = "jpeg (*.jpg)|*.jpg|portable network graphic (*.png)|*.png|Windows bitmap (*.bmp)|*.bmp"
        dlgSaveFile.FileName = Me.AnnotatedImage.ImageURI.LocalPath
        dlgSaveFile.AddExtension = True
        If dlgSaveFile.ShowDialog() = DialogResult.OK Then
            If dlgSaveFile.FileName.Length > 0 Then
                SaveImage(New Uri(dlgSaveFile.FileName))
                Return True
            End If
        End If
        Return False
    End Function

    Public Overloads Function SaveImage() As Boolean
        If Me.oAnnotatedImage.ImageURI Is Nothing Then
            Debug.WriteLine("No URI present, showing filedialog ...", "AnnotatedsRGBImage.SaveImage")
            Return Me.SaveImageAs
        Else
            Return Me.SaveImageAs

            '      'Check if image needs to be saved!
            'If Me.bModifiedImage Then
            '  Debug.WriteLine("Using current URI", "AnnotatedsRGBImage.SaveImage")
            '  If Me.SaveImage(Me.oAnnotatedImage.ImageURI) Then
            '    Me.ModifiedImage = False
            '    Return True
            '  Else
            '    Return False
            '  End If
            'Else
            '  Debug.WriteLine("No need to save, image not modified", "AnnotatedsRGBImage.SaveImage")
            '  Return True
            'End If
        End If
    End Function

    Public Overloads Function SaveImage(ByVal oURI As Uri) As Boolean
        Dim bresult As Boolean = Me.oAnnotatedImage.SaveImage(oURI)
        If bresult Then Me.ModifiedImage = False
        Return bresult
    End Function

    Public Overloads Function LoadImage() As Boolean
        'Adds a dialog to deeper lying layers
        dlgOpenFile.Title = "Load an image"
        dlgOpenFile.Filter = "Image files (*.jpg, *.png, *.bmp)|*.jpg;*.png;*.bmp|jpeg (*.jpg)|*.jpg|portable network graphic (*.png)|*.png|Windows bitmap (*.bmp)|*.bmp"
        dlgOpenFile.Multiselect = False
        dlgOpenFile.ShowDialog()
        If dlgOpenFile.FileName.Length > 0 Then
            Dim bResult As Boolean = LoadImage(New Uri(dlgOpenFile.FileName))
            MsgBox(dlgOpenFile.FileName)
            If Not bResult Then
                SkippableMessage.Show(Me.ParentForm, "Load Error", "Error loading image", "Error loading image " & dlgOpenFile.FileName, False, False)
            End If
            Return bResult
        Else
            Return False
        End If
    End Function

    Public Overloads Function LoadImage(ByVal ouri As Uri) As Boolean
        If Me.oAnnotatedImage.LoadImage(ouri) Then
            Me.ModifiedImage = False
            RefreshStatusBar()
            'Dim rc As Rectangle = Me.ClientRectangle
            'Dim zoom As Single = 2 * Math.Min(rc.Width / (Width + 2), rc.Height / (Height + 2))

            'Me.oAnnotatedImage.DisplayZoom = zoom

            If ouri.IsFile = False Then
                'No file menu in that case!
                If Not Me.ParentForm.Menu Is Nothing Then
                    If Me.ParentForm.Menu.MenuItems.Item(0).Text = "File" Then
                        'Me.ParentForm.Menu.MenuItems.Item(0).Enabled = False
                    End If
                End If
                Return True
            Else
                'File menu is active
                If Not Me.ParentForm.Menu Is Nothing Then
                    If Me.ParentForm.Menu.MenuItems.Item(0).Text = "File" Then
                        Me.ParentForm.Menu.MenuItems.Item(0).Enabled = True
                    End If
                End If
            End If
            Return True
        Else
            Return False
        End If

    End Function

    Public Overloads Sub LoadAnnotatedImage()
        'Load an image and corresponding annotation, IF it is a file
        '(if its a web resource this is tricky due to the use of custom httphandlers using encryption)
        If LoadImage() Then
            If Me.AnnotatedImage.ImageURI.IsFile Then
                'Whatever the outcome of this load, we set the URI to
                Dim strSVGFilename As String = System.IO.Path.ChangeExtension(Me.AnnotatedImage.ImageURI.LocalPath, ".svg")
                Me.AnnotatedImage.AnnotationsURI = New Uri(strSVGFilename)
                Me.LoadAnnotations(Me.AnnotatedImage.AnnotationsURI)
            End If
        End If
    End Sub

    Public Overloads Sub LoadAnnotatedImage(ByVal ouri As Uri)
        'Load an image and corresponding annotation, IF it is a file
        '(if its a web resource this is tricky due to the use of custom httphandlers using encryption)
        If LoadImage(ouri) Then
            If ouri.IsFile Then
                Dim strSVGFilename As String = System.IO.Path.ChangeExtension(ouri.LocalPath, ".svg")
                Me.LoadAnnotations(New Uri(strSVGFilename))

            End If
        Else
            SkippableMessage.Show(Me.ParentForm, "Load Error", "Error loading image", "Error loading image " & ouri.LocalPath, False, False)
        End If
    End Sub

    Public Overloads Function SaveAnnotatedImage() As Boolean
        'Save an image and corresponding annotation, IF it is a file
        '(if its a web resource this is tricky due to the use of custom httphandlers using encryption)
        If Me.SaveImage() Then
            If Me.AnnotatedImage.ImageURI.IsFile Then
                Dim strSVGFilename As String = System.IO.Path.ChangeExtension(Me.AnnotatedImage.ImageURI.LocalPath, ".svg")
                Return Me.SaveAnnotations(New Uri(strSVGFilename))
            Else
                Return Me.SaveAnnotations()
            End If
        Else
            Return False
        End If
    End Function

    Public Overloads Sub SaveAnnotatedImage(ByVal ouri As Uri)
        'Save an image and corresponding annotation, IF it is a file
        If ouri.IsFile Then
            If Me.SaveImage(ouri) Then
                Dim strSVGFilename As String = System.IO.Path.ChangeExtension(ouri.LocalPath, ".svg")
                If Not Me.SaveAnnotations(New Uri(strSVGFilename)) Then
                    SkippableMessage.Show(Me.ParentForm, "SaveError", "Save Error", "Error saving SVG annotation " & strSVGFilename, False, False)
                End If
            Else
                SkippableMessage.Show(Me.ParentForm, "SaveError", "Save Error", "Error saving image " & ouri.LocalPath, False, False)
            End If
        Else
            'Cannot use this function with a web URI
            SkippableMessage.Show(Me.ParentForm, "SaveError", "Save Error", "Cannot use SaveAnnotatedImage(URI) with web URI", False, False)
        End If
    End Sub

    Public Overloads Sub SaveAnnotatedImageAs()
        'Save an image and corresponding annotation, IF it is a file
        '(if its a web resource this is tricky due to the use of custom httphandlers using encryption)
        If Me.SaveImageAs() Then
            Dim oUri As Uri = Me.oAnnotatedImage.ImageURI
            If oUri.IsFile Then
                Dim strSVGFilename As String = System.IO.Path.ChangeExtension(oUri.LocalPath, ".svg")
                Me.SaveAnnotations(New Uri(strSVGFilename))
            Else
                'If an URI is present for the annotation we try that!
                Me.AnnotatedImage.SaveAnnotations(oUri)
            End If
        End If
    End Sub
#End Region

    Public Sub AddMenus()
        'Add standard menus to parent if necessary
        'Make distinction when in 'WEB' mode, i.e when image is URI: no File menu
        'Do not call during constructor, because parentform is not set yet!

        'We are using a very simple Open and Save strategy for the annotations:
        ' - In file mode annotations are always loaded and saved together with an image, using the 
        '   same name with an svg extension
        ' - in web mode we are counting on the presence of 2 URI's, and only the save button will be present.

        If Me.ParentForm Is Nothing Then Exit Sub

        If Me.ParentForm.Menu Is Nothing Then Me.ParentForm.Menu = New MainMenu

        'Add File items
        Dim mnuFile As MenuItem = ParentForm.Menu.MenuItems.Add("File")
        mnuFile.Index = 0
        Dim mniOpen As New MenuItem("&Open", New System.EventHandler(AddressOf Me.FileMenuOpenClick), Shortcut.CtrlO)
        Dim mniSave As New MenuItem("&Save", New System.EventHandler(AddressOf Me.FileMenuSaveClick), Shortcut.CtrlS)
        Dim mniSaveAs As New MenuItem("&Save as", New System.EventHandler(AddressOf Me.FileMenuSaveAsClick), Shortcut.CtrlShiftS)
        mnuFile.MenuItems.Add(mniOpen)
        mnuFile.MenuItems.Add(mniSave)
        mnuFile.MenuItems.Add(mniSaveAs)
        mnuFile.MenuItems.Add(New MenuItem("-"))
        Dim mniInfo As New MenuItem("Info", New System.EventHandler(AddressOf Me.FileMenuInfoClick), Shortcut.CtrlI)
        mnuFile.MenuItems.Add(mniInfo)

        Dim mnuView As MenuItem = ParentForm.Menu.MenuItems.Add("View")
        mnuView.Index = 1
        Dim mniZoomIn As MenuItem = mnuView.MenuItems.Add("Zoom In", New System.EventHandler(AddressOf Me.ViewMenuZoomInClick))
        Dim mniZoomOut As MenuItem = mnuView.MenuItems.Add("Zoom Out", New System.EventHandler(AddressOf Me.ViewMenuZoomOutClick))
        Dim mniNoZoom As MenuItem = mnuView.MenuItems.Add("No Zoom", New System.EventHandler(AddressOf Me.ViewMenuNoZoomClick))
        mnuView.MenuItems.Add(New MenuItem("-"))
        Dim mniSetPhysicalZoom1 As MenuItem = mnuView.MenuItems.Add("True size", New System.EventHandler(AddressOf Me.ViewMenuSetPhysicalZoom1Click))
        Dim mniSetPhysicalZoom As MenuItem = mnuView.MenuItems.Add("Set Physical Zoom", New System.EventHandler(AddressOf Me.ViewMenuSetPhysicalZoomClick))
        Dim mniSetResolution As MenuItem = mnuView.MenuItems.Add("Set Resolution", New System.EventHandler(AddressOf Me.ViewMenuSetResolutionClick))
        mnuView.MenuItems.Add(New MenuItem("-"))
        mnuView.MenuItems.Add(New MenuItem("&ROI table manager", New System.EventHandler(AddressOf Me.ViewMenuShowAnnotationManagerClick), Shortcut.CtrlM))
        mniDisplayPixel = mnuView.MenuItems.Add("Display pixel values")

        'Add menu items to view and tools menu ...
        Dim i As Integer
        For i = 0 To strPixelDisplayColorSpaceNames.GetUpperBound(0)
            Dim mnuItem As New MenuItem(strPixelDisplayColorSpaceNames(i), New System.EventHandler(AddressOf Me.PixelDisplayColorSpaceMenuItemEventHandler))
            mniDisplayPixel.MenuItems.Add(mnuItem)
        Next
        PixelDisplayColorSpace = PixelDisplayColorSpaceTypes.None
    End Sub
    Public Sub AddMenuswithBitmapLoad()
        'Add standard menus to parent if necessary
        'Make distinction when in 'WEB' mode, i.e when image is URI: no File menu
        'Do not call during constructor, because parentform is not set yet!

        'We are using a very simple Open and Save strategy for the annotations:
        ' - In file mode annotations are always loaded and saved together with an image, using the 
        '   same name with an svg extension
        ' - in web mode we are counting on the presence of 2 URI's, and only the save button will be present.

        If Me.ParentForm Is Nothing Then Exit Sub

        If Me.ParentForm.Menu Is Nothing Then Me.ParentForm.Menu = New MainMenu

        'Add File items
        Dim mnuFile As MenuItem = ParentForm.Menu.MenuItems.Add("File")
        mnuFile.Index = 0
        Dim mniOpen As New MenuItem("&Load Map", New System.EventHandler(AddressOf Me.LoadAnnotationsClicked), Shortcut.CtrlO)
        Dim mniSaveAs As New MenuItem("&Save as", New System.EventHandler(AddressOf Me.FileMenuSaveAsClick), Shortcut.CtrlShiftS)
        Dim mniAppend As New MenuItem("&Append To 3D Maps", New System.EventHandler(AddressOf Me.AppendAnnotations), Shortcut.CtrlShiftS)
        mnuFile.MenuItems.Add(mniOpen)
        mnuFile.MenuItems.Add(mniSaveAs)
        mnuFile.MenuItems.Add(mniAppend)
        Dim mnuView As MenuItem = ParentForm.Menu.MenuItems.Add("View")
        mnuView.Index = 1
        Dim mniZoomIn As MenuItem = mnuView.MenuItems.Add("Zoom In", New System.EventHandler(AddressOf Me.ViewMenuZoomInClick))
        Dim mniZoomOut As MenuItem = mnuView.MenuItems.Add("Zoom Out", New System.EventHandler(AddressOf Me.ViewMenuZoomOutClick))
        Dim mniNoZoom As MenuItem = mnuView.MenuItems.Add("No Zoom", New System.EventHandler(AddressOf Me.ViewMenuNoZoomClick))
        mnuView.MenuItems.Add(New MenuItem("-"))
        Dim mniSetPhysicalZoom1 As MenuItem = mnuView.MenuItems.Add("True size", New System.EventHandler(AddressOf Me.ViewMenuSetPhysicalZoom1Click))
        Dim mniSetPhysicalZoom As MenuItem = mnuView.MenuItems.Add("Set Physical Zoom", New System.EventHandler(AddressOf Me.ViewMenuSetPhysicalZoomClick))
        Dim mniSetResolution As MenuItem = mnuView.MenuItems.Add("Set Resolution", New System.EventHandler(AddressOf Me.ViewMenuSetResolutionClick))
        mnuView.MenuItems.Add(New MenuItem("-"))
        mnuView.MenuItems.Add(New MenuItem("&ROI table manager", New System.EventHandler(AddressOf Me.ViewMenuShowAnnotationManagerClick), Shortcut.CtrlM))
        mniDisplayPixel = mnuView.MenuItems.Add("Display pixel values")

        'Add menu items to view and tools menu ...
        Dim i As Integer
        For i = 0 To strPixelDisplayColorSpaceNames.GetUpperBound(0)
            Dim mnuItem As New MenuItem(strPixelDisplayColorSpaceNames(i), New System.EventHandler(AddressOf Me.PixelDisplayColorSpaceMenuItemEventHandler))
            mniDisplayPixel.MenuItems.Add(mnuItem)
        Next
        PixelDisplayColorSpace = PixelDisplayColorSpaceTypes.None
    End Sub

    Public Overloads Sub EnableMenus(ByVal mnu As Menu, ByVal bEnable As Boolean)
        EnableMenus(mnu, bEnable, False)
    End Sub

    Public Overloads Sub EnableMenus(ByVal mnu As Menu, ByVal bEnable As Boolean, ByVal bAll As Boolean)
        'Enable/disable all menus under mnu, except open ...
        'Also ignore any entries under Help
        Dim mni As MenuItem
        For Each mni In mnu.MenuItems
            'Recurse
            If mni.IsParent Then
                If String.Compare(mni.Text, "Help", True) <> 0 Then EnableMenus(mni, bEnable, bAll)
            End If

            If Not mni.Parent Is Me.ParentForm.Menu And (mni.Shortcut <> Shortcut.CtrlO Or bAll) Then
                Debug.WriteLine("Setting menu " & mni.Text & " to " & bEnable, "EnableMenus")
                mni.Enabled = bEnable
            End If
        Next
    End Sub

    Public Sub SetFormMenus(ByVal frm As Form, ByVal strText() As String, ByVal bEnable() As Boolean)
        If Not frm Is Nothing Then
            Dim i As Integer
            For i = 0 To strText.Length - 1
                SetFormMenu(frm, strText(i), bEnable(i), False)
            Next
        End If
    End Sub

    Public Sub SetFormMenu(ByVal frm As Form, ByVal strText As String, ByVal bEnable As Boolean, ByVal bCheck As Boolean)
        If Not frm Is Nothing Then
            SetMenu(frm.Menu, strText, bEnable, bCheck)
        End If
    End Sub

    Private Function SetMenu(ByVal mnu As Menu, ByVal strText As String, ByVal bEnable As Boolean, ByVal bCheck As Boolean) As Boolean
        'Enable/disable a menu...
        If mnu Is Nothing Then Exit Function

        Dim mni As MenuItem
        For Each mni In mnu.MenuItems
            If String.Compare(strText, mni.Text, True) = 0 Then
                mni.Enabled = bEnable
                mni.Checked = bCheck
                Return True
            Else
                'Recurse if necessary
                If mni.IsParent Then
                    If SetMenu(mni, strText, bEnable, bCheck) Then Return True
                End If
            End If
        Next
        Return False
    End Function

#End Region

#Region "Private methods"

    Private Sub SizeControls()
        'Size the constituent controls according to the size of the annotatedImage
        'Call this routine when it changes size, and make sure that any parent control
        'intercepts the resulting resize events
        Dim iControlWidth As Integer = Me.oAnnotatedImage.Width
        Dim iControlHeight As Integer = Me.oAnnotatedImage.Height
        Me.oAnnotatedImage.Location = New Point(0, 0)
        Me.stbImage.Location = New Point(0, iControlHeight)
        Me.stbImage.Width = iControlWidth
        Me.Size = New Size(CInt(Math.Min(iControlWidth, MaximimumSize.Width)), CInt(Math.Min(iControlHeight + stbImage.Height, MaximimumSize.Height)))
        Debug.WriteLine("User control set to " & Me.Size.ToString(), "AnnotatedsRGBImage.SizeControls")
    End Sub

    Private Sub RefreshStatusBar()
        'Show image information in the status bar, except cursor position and values
        With Me.AnnotatedImage
            If .BitmapPresent Then
                Dim oSize As Size = .ImageSize
                stbImage.Panels(0).Text = oSize.Width & " x " & oSize.Height & ", " & _
                    .ColorDepth & " bpp, " & _
                    .Resolution.ToString("####.#") & " dpi"
                stbImage.Panels(1).Text = "Zoom: image " & .DisplayZoom.ToString("##.##") & _
                  ", physical " & .PhysicalZoom.ToString("##.##")
                stbImage.Panels(2).Text = "Window " & .PixelAveragingWindowSize
            End If

        End With
    End Sub
#End Region

#Region "Control Menu Event handling"

    Private Sub FileMenuOpenClick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        LoadAnnotatedImage()
    End Sub

    Private Sub FileMenuInfoClick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Dim strInfo As String
        strInfo = "Image URI: " & Me.oAnnotatedImage.ImageURI.ToString
        If Me.ModifiedImage Then
            strInfo = strInfo & " (modified)"
        End If
        strInfo = strInfo & vbNewLine

        strInfo = strInfo & "Annotation URI: " & Me.oAnnotatedImage.AnnotationsURI.ToString
        If Me.ModifiedAnnotations Then
            strInfo = strInfo & " (modified)"
        End If
        strInfo = strInfo & vbNewLine

        MessageBox.Show(strInfo, "Annotated image info", MessageBoxButtons.OK, MessageBoxIcon.Information)
    End Sub

    Private Sub FileMenuSaveClick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        SaveAnnotatedImage()
    End Sub

    Private Sub LoadAnnotationsClicked(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Me.LoadAnnotations()
    End Sub

    Private Sub FileMenuSaveAsClick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Me.SaveAnnotationsAs()
    End Sub
    Private Sub AppendAnnotations(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Me.AppendAnnotationsAs()
    End Sub
    Public Overloads Sub AppendAnnotationsAs()
        'Adds a dialog to deeper lying layers
        dlgOpenFile.Title = "Append an SVG annotations file"
        dlgOpenFile.Filter = "Scalable Vector graphics (*.svg)|*.svg"
        dlgOpenFile.Multiselect = False
        dlgOpenFile.ShowDialog()

        If dlgOpenFile.FileName.Length > 0 Then
            Me.oAnnotatedImage.AppendAnnotations(New Uri(dlgOpenFile.FileName))
            Me.ModifiedAnnotations = False
        End If
    End Sub

    Private Sub ViewMenuNoZoomClick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        'No Zoom 
        Me.oAnnotatedImage.DisplayZoom = 1
    End Sub

    Private Sub ViewMenuSetPhysicalZoom1Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        'Set physical zoom, allowing side-by side comparisons
        Me.oAnnotatedImage.PhysicalZoom = 1
    End Sub

    Private Sub ViewMenuSetPhysicalZoomClick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        'Set physical zoom, allowing side-by side comparisons
        Dim strZoom As String = InputBox.Show("Enter the physical zoom", "Physical zoom", CStr(Me.oAnnotatedImage.PhysicalZoom)).Text
        If IsNumeric(strZoom) Then
            Dim objCulture As New System.Globalization.CultureInfo("")
            Me.oAnnotatedImage.PhysicalZoom = Single.Parse(strZoom, objCulture)
        Else
            MessageBox.Show("Invalid entry", "Physical zoom", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End If
    End Sub

    Private Sub ViewMenuSetResolutionClick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        'Set resolution
        Dim strZoom As String = InputBox.Show("Enter the image resolution in DPI", "Resolution", "96").Text
        If IsNumeric(strZoom) Then
            Dim objCulture As New System.Globalization.CultureInfo("")
            Dim sRes As Single = Single.Parse(strZoom, objCulture)
            Me.oAnnotatedImage.Resolution = sRes
        Else
            MessageBox.Show("Invalid entry", "Resolution", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End If
    End Sub

    Private Sub ViewMenuZoomInClick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        'Zoom in
        Me.oAnnotatedImage.DisplayZoom = CSng(Me.oAnnotatedImage.DisplayZoom * 1.25)
    End Sub

    Private Sub ViewMenuZoomOutClick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        'Zoom in
        Me.oAnnotatedImage.DisplayZoom = CSng(Me.oAnnotatedImage.DisplayZoom / 1.25)
    End Sub

    Private Sub ViewMenuShowAnnotationManagerClick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Dim objMenu As MenuItem = CType(sender, MenuItem)
        'objMenu.Checked = Not objMenu.Checked
        Me.AnnotatedImage.ShowAnnotationsManager(Not objMenu.Checked)
    End Sub

    Protected Sub PixelDisplayColorSpaceMenuItemEventHandler(ByVal sender As System.Object, ByVal e As System.EventArgs)
        PixelDisplayColorSpace = sender.index
    End Sub

#End Region

#Region "Annotated image event handling"

    Private Sub AnnotatedImage_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles oAnnotatedImage.Resize
        'Adjust sibling controls too
        Debug.WriteLine("Resizing AnnotatedsRGBImages controls", "oAnnotatedImage_Resize")
        SizeControls()
    End Sub

    Private Sub AnnotatedImage_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles oAnnotatedImage.MouseMove
        'Update the panel with the cursor position and pixel value in appropriate color space
        If Not Me.oAnnotatedImage.BitmapPresent Then Exit Sub

        Dim sRGB(2) As Single
        Dim objClientCoordinates As New Point(e.X, e.Y)
        Dim objImageCoordinates As Point = MetaView.AnnotatedImage.ClientToImageCoordinates(objClientCoordinates, Me.oAnnotatedImage.DisplayZoom, Me.oAnnotatedImage.DisplayOffset)

        Dim strText As String, sPixelToPhysical As Single = CSng(2.54 / Me.oAnnotatedImage.Resolution)

        strText = "Pos (" & objImageCoordinates.X & " = " & Format(objImageCoordinates.X * sPixelToPhysical, ".##") & " cm," & _
          objImageCoordinates.Y & " = " & Format(objImageCoordinates.Y * sPixelToPhysical, ".##") & " cm)"
        If Me.PixelDisplayColorSpace = PixelDisplayColorSpaceTypes.None Then
        Else
            Dim iWindowSize As Integer = Me.oAnnotatedImage.PixelAveragingWindowSize
            If iWindowSize > 1 Then
                'Compute average in window, and draw that rectangle ...
                Dim objImageRect As New Rectangle(objImageCoordinates.X - iWindowSize \ 2, objImageCoordinates.Y - iWindowSize \ 2, iWindowSize, iWindowSize)
                Dim objClientRect As Rectangle = MetaView.AnnotatedImage.ImageToClientCoordinates(objImageRect, Me.oAnnotatedImage.DisplayZoom, Me.oAnnotatedImage.DisplayOffset)
                ImageProcessing.Average(Me.oAnnotatedImage.Bitmap, objImageRect, sRGB)

                Me.oAnnotatedImage.DrawErasableRectangle(objClientRect)
            Else
                Dim objColor As System.Drawing.Color = Me.oAnnotatedImage.Bitmap.GetPixel(objImageCoordinates.X, objImageCoordinates.Y)
                sRGB(ColorUtil.RGB.red) = objColor.R
                sRGB(ColorUtil.RGB.green) = objColor.G
                sRGB(ColorUtil.RGB.blue) = objColor.B
            End If
            Select Case PixelDisplayColorSpace
                Case PixelDisplayColorSpaceTypes.GammasRGB
                    strText = strText & ": sR*G*B*(" & ColorUtil.ToString(sRGB, 2) & ")"
                Case PixelDisplayColorSpaceTypes.CIEXYZ
                    Dim sXYZ(2) As Single
                    ColorUtil.GammaRGBToRGB(sRGB, sRGB)
                    objColor.sRGBtoXYZ(sRGB, sXYZ)
                    strText = strText & ": CIE XYZ(" & ColorUtil.ToString(sXYZ, 2) & ")"
                Case PixelDisplayColorSpaceTypes.CIELab
                    Dim sLab(2) As Single
                    ColorUtil.GammaRGBToRGB(sRGB, sRGB)
                    objColor.sRGBToCIELab(sRGB, sLab)
                    strText = strText & ": CIE L*a*b*(" & ColorUtil.ToString(sLab, 2) & ")"
                Case PixelDisplayColorSpaceTypes.sRGB
                    ColorUtil.GammaRGBToRGB(sRGB, sRGB)
                    strText = strText & ": sRGB(" & ColorUtil.ToString(sRGB, 2) & ")"
            End Select
        End If
        stbImage.Panels(3).Text = strText
    End Sub

    Private Sub AnnotatedImage_DisplayZoomChanged(ByVal sDisplayZoom As Single) Handles oAnnotatedImage.DisplayZoomChanged
        RefreshStatusBar()
    End Sub

    Private Sub AnnotatedImage_BitmapDataChanged(ByVal oBitmap As System.Drawing.Bitmap) Handles oAnnotatedImage.BitmapDataChanged
        Me.ModifiedImage = True
        SetFormMenu(Me.ParentForm, "&Save", True, False)
        RaiseEvent BitmapDataChanged(oBitmap)
    End Sub

    Private Sub AnnotatedImage_BitmapChanged(ByVal objBitmap As System.Drawing.Bitmap) Handles oAnnotatedImage.BitmapChanged
        If objBitmap Is Nothing Then
            If Not Me.ParentForm Is Nothing Then Me.EnableMenus(Me.ParentForm.Menu, False)
        Else
            If Not Me.ParentForm Is Nothing Then Me.EnableMenus(Me.ParentForm.Menu, True)
        End If

        RefreshStatusBar()

        Me.ModifiedImage = False
        Me.ModifiedAnnotations = False
        RaiseEvent BitmapChanged(objBitmap)
    End Sub

    Private Sub AnnotatedImage_PixelAveragingWindowSizeChanged(ByVal iWindowSize As Integer) Handles oAnnotatedImage.PixelAveragingWindowSizeChanged
        RefreshStatusBar()
    End Sub

    Private Sub AnnotatedImage_AnnotationItemSelected(ByVal obj As Object) Handles oAnnotatedImage.AnnotationItemSelected
        Debug.WriteLine("AnnotatedsRGBImage.AnnotationItemSelected")
        RaiseEvent AnnotationItemSelected(obj)
    End Sub

    Private Sub AnnotatedImage_AnnotationCreationDone(ByVal objAnnotation As AnnotatedImage.Annotation) Handles oAnnotatedImage.AnnotationCreationDone
        Debug.WriteLine("AnnotatedsRGBImage.AnnotationCreationDone")
        RaiseEvent AnnotationCreationDone(objAnnotation)
    End Sub

    Private Sub AnnotatedImage_AnnotationCreationCanceled(ByVal objAnnotation As MetaView.AnnotatedImage.Annotation) Handles oAnnotatedImage.AnnotationCreationCanceled
        Debug.WriteLine("AnnotatedsRGBImage.AnnotationCreationCanceled")
        RaiseEvent AnnotationCreationCanceled(objAnnotation)
    End Sub

    Private Sub AnnotatedImage_AnnotationCreationMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs, ByVal objAnnotation As MetaView.AnnotatedImage.Annotation) Handles oAnnotatedImage.AnnotationCreationMouseMove
        RaiseEvent AnnotationCreationMouseMove(e, objAnnotation)
    End Sub

    Private Sub AnnotatedImage_AnnotationCreationPointAdded(ByVal objAnnotation As MetaView.AnnotatedImage.Annotation) Handles oAnnotatedImage.AnnotationCreationPointAdded
        Debug.WriteLine("AnnotatedsRGBImage.AnnotationCreationPointAdded")
        RaiseEvent AnnotationCreationPointAdded(objAnnotation)
    End Sub

    Private Sub AnnotatedImage_AnnotationCreationPointRemoved(ByVal objAnnotation As MetaView.AnnotatedImage.Annotation) Handles oAnnotatedImage.AnnotationCreationPointRemoved
        Debug.WriteLine("AnnotatedsRGBImage.AnnotationCreationPointRemoved")
        RaiseEvent AnnotationCreationPointRemoved(objAnnotation)
    End Sub

    Private Sub AnnotatedImage_AnnotationsChanged(ByVal sender As Object) Handles oAnnotatedImage.AnnotationsChanged
        Me.ModifiedAnnotations = True
        SetFormMenu(Me.ParentForm, "&Save", True, False)
        RaiseEvent AnnotationsChanged(sender)
    End Sub

    Private Sub AnnotatedImage_AnnotationsManagerVisibleChanged(ByVal bVisible As Boolean) Handles oAnnotatedImage.AnnotationsManagerVisibleChanged
        Me.SetFormMenu(Me.ParentForm, "&Annotations manager", True, bVisible)
    End Sub

#End Region

End Class
